home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Camelot / Camelot 043 (1989-06)(Swedish User Group of Amiga)(SE)(PD)[WB].zip / Camelot 043 (1989-06)(Swedish User Group of Amiga)(SE)(PD)[WB].adf / zc / expr.c < prev    next >
C/C++ Source or Header  |  1989-03-08  |  10KB  |  566 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    expr.c
  12.  *
  13.  *    Expression parse routines
  14.  *
  15.  *    All routines return either NULL or a valid tree
  16.  *        binop nodes have non-null left and right
  17.  *        unop nodes have non-null left
  18.  *
  19.  *    Special nodes:
  20.  *        '(' : function call.  left:name-expr right:args 
  21.  *        ',': if part of function arg list, ival:num. descendants
  22.  *        '?' : ?switch.  left:test-expr right:':' part
  23.  *          ':' : left:true-expr right:false-expr
  24.  *        TCONV: left:convertee tptr:type-list
  25.  *        TSIZEOF: tptr:type-list
  26.  *
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include "param.h"
  31. #include "nodes.h"
  32. #include "tok.h"
  33.  
  34. extern NODEP cur;
  35. NODEP getnode();
  36. NODEP opt_follow();
  37.  
  38. extern int oflags[];
  39. #define debug oflags['x'-'a']
  40.  
  41. advnode()
  42. {
  43.     cur = getnode();
  44. }
  45.  
  46. fadvnode()
  47. {
  48.     freenode(cur);
  49.     cur = getnode();
  50. }
  51.  
  52. NODEP
  53. gete_or_ty()
  54. {
  55.     NODEP getexpr(), makecast();
  56.     NODEP rv;
  57.  
  58.     if (is_ty_start()) {
  59.         rv = makecast();
  60.         if (debug) {
  61.             printf("TY_X");
  62.             printnode(rv);
  63.         }
  64.         return rv;
  65.     } else
  66.         return getexpr();
  67. }
  68.  
  69. /* call this for any expr including comma's */
  70. NODEP
  71. getexpr()
  72. {
  73.     NODEP np, get_f_expr();
  74.  
  75.     np = get_f_expr(0);
  76.     return np;
  77. }
  78.  
  79. NODEP
  80. get_f_expr(flg)
  81. int flg;
  82. {
  83.     NODEP assignx();
  84.     register NODEP op, lpart, rpart;
  85.     int i = 0;
  86.  
  87.     lpart = assignx();
  88.     if (lpart == NULL) {
  89.         return NULL;
  90.     }
  91.     i++;
  92. more:
  93.     if (cur->e_token != ',')
  94.         return lpart;
  95.  
  96.     op = cur;  advnode();
  97.     rpart = assignx();
  98.     if (rpart == NULL) {
  99.         error("',' expr syntax");
  100.         return lpart;
  101.     }
  102.     i++;
  103.     op->n_left = lpart;
  104.     op->n_right = rpart;
  105.     op->e_type = E_BIN;
  106.     op->e_ival = flg ? i : 0;
  107.     lpart = op;
  108.     if (debug) {
  109.         printf("COMMA");
  110.         printnode(op);
  111.     }
  112.     goto more;
  113. }
  114.  
  115. /* call this if you want expr w/o comma's */
  116. NODEP
  117. assignx()
  118. {
  119.     NODEP questx();
  120.     register NODEP op, lpart, rpart;
  121.  
  122.     lpart = questx();
  123.     if (lpart == NULL)
  124.         return NULL;
  125.     if (!isassign(cur->e_token) && cur->e_token != '=')
  126.         return lpart;
  127.     op = cur;  advnode();
  128.     rpart = assignx();
  129.     if (rpart == NULL) {
  130.         error("'=op' expr syntax");
  131.         return lpart;
  132.     }
  133.     op->n_left = lpart;
  134.     op->n_right = rpart;
  135.     op->e_type = E_BIN;
  136.     if (debug) {
  137.         printf("ASSIGN");
  138.         printnode(op);
  139.     }
  140.     return op;
  141. }
  142.  
  143. /* call this if you want expr w/o assign's or comma's */
  144. /* i.e. constant-expression */
  145. NODEP
  146. questx()
  147. {
  148.     NODEP binary();
  149.     register NODEP holdq, holdc;
  150.     NODEP qpart, tpart, fpart;
  151.  
  152.     qpart = binary();
  153.     if (qpart == NULL)
  154.         return NULL;
  155.     if (cur->e_token != '?')
  156.         return qpart;
  157.     holdq = cur;  advnode();
  158.     tpart = questx();
  159.     if (tpart == NULL || cur->e_token != ':') {
  160. bad:
  161.         error("'?:' expr syntax");
  162.         return qpart;
  163.     }
  164.     holdc = cur;  advnode();
  165.     fpart = questx();
  166.     if (fpart == NULL) goto bad;
  167.     holdc->n_left = tpart;
  168.     holdc->n_right = fpart;
  169.     holdc->e_type = E_BIN;
  170.     holdq->n_left = qpart;
  171.     holdq->n_right = holdc;
  172.     holdq->e_type = E_BIN;
  173.     if (debug) {
  174.         printf("QUEST");
  175.         printnode(holdq);
  176.     }
  177.     return holdq;
  178. }
  179.  
  180. NODEP
  181. binary()
  182. {
  183.     NODEP unary(), buildbin();
  184.     register NODEP rv, op, e2;
  185.  
  186.     rv = unary();
  187.     if (rv == NULL)
  188.         return NULL;
  189.     rv->e_prec = 0;
  190. more:
  191.     if (cur->e_prec == 0)    /* not binary op */
  192.         return rv;
  193.     op = cur;  advnode();
  194.     e2 = unary();
  195.     if (e2 == NULL) {
  196.         error("bin-op expr syntax");
  197.         return rv;
  198.     }
  199.     e2->e_prec = 0;
  200.     rv = buildbin(rv, op, e2);
  201.     if (debug) {
  202.         printf("BINARY");
  203.         printnode(rv);
  204.     }
  205.     goto more;
  206. }
  207.  
  208. NODEP
  209. buildbin(lpart, op, upart)
  210. NODEP lpart, op, upart;
  211. {
  212.     register NODEP look, tail;
  213.     NODEP rv;
  214.  
  215.     tail = NULL;
  216.     look = lpart;
  217.     for (look=lpart; op->e_prec < look->e_prec; look=look->n_right)
  218.         tail = look;
  219.     if (tail == NULL) {
  220.         op->n_left = lpart;
  221.         op->n_right = upart;
  222.         rv = op;
  223.     } else {
  224.         tail->n_right = op;
  225.         op->n_left = look;
  226.         op->n_right = upart;
  227.         rv = lpart;
  228.     }
  229.     op->e_type = E_BIN;
  230.     return rv;
  231. }
  232.  
  233. NODEP
  234. unary()
  235. {
  236.     register NODEP tp,e1;
  237.     NODEP primary();
  238.  
  239.     if (cur->e_flags & CAN_U) {
  240.         tp = cur;  advnode();
  241.         if (tp->e_prec) {  /* also have BINARY op */
  242.             tp->e_token = UNARY tp->e_token;
  243.             strcat(tp->n_name, "U");
  244.         }
  245.         tp->n_left = unary();
  246.         tp->e_type = E_UNARY;
  247.         goto check;
  248.     } else
  249.     switch (cur->e_token) {
  250.     case '(':
  251.         fadvnode();
  252.         tp = gete_or_ty();
  253.         if (cur->e_token != ')') {
  254.             error("missing )");
  255.         } else
  256.             fadvnode();
  257.         if (tp == NULL)
  258.             return NULL;
  259.         if (tp->e_token == TCONV && tp->n_left == NULL) {
  260.             sprintf(tp->n_name, "cast to");
  261.             tp->n_left = unary();
  262.             tp->e_type = E_UNARY;
  263.         } else {
  264.             tp = opt_follow(tp);
  265.             goto out;
  266.         }
  267.         goto check;
  268.     case K_SIZEOF:
  269.         tp = cur;
  270.         advnode();
  271.         if (cur->e_token == '(') { /* may be type expr */
  272.             fadvnode();
  273.             e1 = gete_or_ty();
  274.             if (cur->e_token != ')') {
  275.                 error("missing )");
  276.             } else
  277.                 fadvnode();
  278.         } else
  279.             e1 = unary();
  280.         if (e1 == NULL) {
  281.             error("sizeof expr syntax");
  282.             return NULL;
  283.         }
  284.         if (e1->e_token == TCONV) {
  285.             freeunit(tp);
  286.             e1->e_token = TSIZEOF;
  287.             sprintf(e1->n_name, "T-sizeof");
  288.             tp = e1;
  289.             tp->e_type = E_LEAF;
  290.             goto out;
  291.         } else {
  292.             tp->e_type = E_UNARY;
  293.             tp->n_left = e1;
  294.         }
  295.         goto check;
  296.     default:
  297.         tp = primary();
  298.         goto out;
  299.     }
  300. check:
  301.     if (tp == NULL) return NULL;
  302.     if (tp->n_left == NULL) {
  303.         error("u-op expr syntax");
  304.         return NULL;
  305.     }
  306. out:
  307.     if (debug) {
  308.         printf("UNARY");
  309.         printnode(tp);
  310.     }
  311.     return tp;
  312. }
  313.  
  314. NODEP
  315. primary()
  316. {
  317.     register NODEP e1;
  318.  
  319.     switch (cur->e_token) {
  320.     case ID:
  321.     case ICON:
  322.     case FCON:
  323.     case SCON:
  324.         e1 = cur;
  325.         e1->e_type = E_LEAF;
  326.         advnode();
  327.         break;
  328.     case '(':
  329.         fadvnode();
  330.         e1 = getexpr();
  331.         if (cur->e_token != ')')
  332.             error("missing )");
  333.         else
  334.             fadvnode();
  335.         break;
  336.     default:
  337.         e1 = NULL;
  338.     }
  339.     if (e1 == NULL)
  340.         return NULL;
  341.     return opt_follow(e1);
  342. }
  343.  
  344. NODEP
  345. opt_follow(np)
  346. NODEP np;
  347. {
  348.     register NODEP tp, e1, t2;
  349.  
  350.     switch (cur->e_token) {
  351.     case '[':
  352.         tp = cur;  advnode();
  353.         e1 = getexpr();
  354.         if (cur->e_token != ']') {
  355.             error("missing ]");
  356.             return np;
  357.         } else {
  358.             t2 = cur;  advnode();
  359.         }
  360.         if (e1 == NULL) {
  361.             error("empty []");
  362.             return np;
  363.         }
  364.         t2->n_left = np;
  365.         t2->n_right = e1;
  366.         t2->e_type = E_BIN;
  367.         t2->e_token = '+';
  368.         strcpy(t2->n_name, "+ [");
  369.  
  370.         tp->n_left = t2;
  371.         tp->e_type = E_UNARY;
  372.         tp->e_token = STAR;
  373.         strcpy(tp->n_name, "U*");
  374.  
  375.         goto out;
  376.     case '(':
  377.         tp = cur;
  378.         advnode();
  379.         e1 = get_f_expr(1);
  380.         if (cur->e_token != ')')
  381.             error("expect )");
  382.         else
  383.             fadvnode();
  384.         tp->n_left = np;
  385.         tp->n_right = e1;
  386.         tp->e_type = E_SPEC;
  387.         goto out;
  388.     case '.':
  389.     case ARROW:
  390.         tp = cur;  advnode();
  391.         if (cur->e_token != ID) {
  392.             error("expect ID");
  393.             return np;
  394.         }
  395.         tp->n_left = np;
  396.         tp->n_right = cur;
  397.         tp->e_type = E_SPEC;
  398.         if (tp->e_token == ARROW) { /* make into (*X).Y */
  399.             tp->e_token = '.';
  400.             strcpy(tp->n_name, ".");
  401.  
  402.             t2 = allocnode();
  403.             t2->e_token = STAR;
  404.             t2->n_left = np;
  405.             t2->e_type = E_UNARY;
  406.             strcpy(t2->n_name, "U*");
  407.  
  408.             tp->n_left = t2;    
  409.         }
  410.         advnode();
  411.         goto out;
  412.     case DOUBLE '+':
  413.     case DOUBLE '-':
  414.         tp = cur;  advnode();
  415.         tp->e_token = (tp->e_token == DOUBLE '+') ? POSTINC : POSTDEC;
  416.         strcat(tp->n_name, "post");
  417.         tp->n_left = np;
  418.         tp->e_type = E_UNARY;
  419.         goto out;
  420.     default:
  421.         return np;
  422.     }
  423. out:
  424.     return opt_follow(tp);
  425. }
  426.  
  427. /* restricted version of unary for declarations or coertions */
  428. /* allows NULL primary part */
  429. NODEP
  430. declarator()
  431. {
  432.     register NODEP tp,e1;
  433.     NODEP ty_primary(), ty_follow();
  434.  
  435.     if (cur->e_token == '*') {
  436.         tp = cur;
  437.         tp->e_token = UNARY tp->e_token;
  438.         strcat(tp->n_name, "U");
  439.         advnode();
  440.         tp->n_left = declarator();
  441.         return tp;
  442.     } else
  443.     switch (cur->e_token) {
  444.     case '(':
  445.         tp = cur;
  446.         advnode();
  447.         e1 = declarator();
  448.         if (cur->e_token != ')') {
  449.             error("expect )");
  450.         } else
  451.             fadvnode();
  452.         if (e1 == NULL) {    /* special "fun of" */
  453.             /* left and right already NULL */
  454.             return ty_follow(tp);
  455.         } else {
  456.             freeunit(tp);
  457.             return ty_follow(e1);
  458.         }
  459.     default:
  460.         return ty_primary();
  461.     }
  462. }
  463.  
  464. /* restricted version of primary for "declarator" */
  465. NODEP
  466. ty_primary()
  467. {
  468.     register NODEP e1;
  469.     NODEP ty_follow();
  470.  
  471.     switch (cur->e_token) {
  472.     case ID:
  473.         e1 = cur;
  474.         advnode();
  475.         break;
  476.     case '(':
  477.         fadvnode();
  478.         e1 = declarator();
  479.         if (cur->e_token != ')')
  480.             error("expect )");
  481.         else
  482.             fadvnode();
  483.         break;
  484.     default:
  485.         e1 = NULL;
  486.     }
  487.     return ty_follow(e1);
  488. }
  489.  
  490. /* restricted version of opt_follow for 'declarator' */
  491. /* allow null [] */
  492. NODEP
  493. ty_follow(np)
  494. NODEP np;
  495. {
  496.     register NODEP tp, e1;
  497.     NODEP ty_args();
  498.  
  499.     switch (cur->e_token) {
  500.     case '[':
  501.         tp = cur;
  502.         advnode();
  503.         e1 = questx();
  504.         if (cur->e_token != ']')
  505.             error("expect ]");
  506.         else
  507.             fadvnode();
  508.         tp->n_left = np;
  509.         tp->n_right = e1;
  510.         goto out;
  511.     case '(':
  512.         tp = cur;
  513.         advnode();
  514.         e1 = ty_args();    /* allow args of fun to follow */
  515.         if (cur->e_token != ')')
  516.             error("expect )");
  517.         else
  518.             fadvnode();
  519.         tp->n_left = np;
  520.         tp->n_right = e1;
  521.         goto out;
  522.     default:
  523.         return np;
  524.     }
  525. out:
  526.     return ty_follow(tp);
  527. }
  528.  
  529. /* called for args of function declaration or NULL */
  530. NODEP
  531. ty_args()
  532. {
  533.     NODEP opt_id();
  534.     register NODEP rv, tail, new;
  535.  
  536.     rv = opt_id();
  537.     if (rv == NULL)
  538.         return NULL;
  539.     tail = rv;
  540. more:
  541.     if (cur->e_token != ',')
  542.         return rv;
  543.     fadvnode();
  544.     new = opt_id();
  545.     if (new == NULL) {
  546.         error("expect as-op value");
  547.         return rv;
  548.     }
  549.     tail->n_left = new;
  550.     tail = new;
  551.     goto more;
  552. }
  553.  
  554. NODEP
  555. opt_id()
  556. {
  557.     NODEP rv;
  558.  
  559.     if (cur->e_token == ID) {
  560.         rv = cur;
  561.         advnode();
  562.         return rv;
  563.     } else
  564.         return NULL;
  565. }
  566.